package command;

import condition.Condition;

import elements.Robot;
import exceptions.IllegalCommandException;
import exceptions.IllegalConditionException;

/**
 * A class of composed commands representing the if command.
 * 
 * @version	3.0
 * @author 	Lies Tambeur 	r0264469	2Bcwsbbh
 * @author	Eline Vanrykel	r0264543	2Bcwselt
 *
 */

public class If extends ComposedCommand {
	/**
	 * The condition of the If.
	 */
	protected Condition condition;
	/**
	 * The ifCommand of the If.
	 */
	protected Command ifCommand;
	/**
	 * The elseCommand of the If.
	 */
	protected Command elseCommand;
	/**
	 * Returns the condition of the If.
	 * @return	The condition of the If.
	 */
	protected Condition getCondition() {
		return this.condition;
	}
	/**
	 * Returns the ifCommand of the If.
	 * @return	The ifCommand of the If.
	 */
	protected Command getIfCommand() {
		return this.ifCommand;
	}
	/**
	 * Returns the elseCommand of the If.
	 * @return	The elseCommand of the If.
	 */
	protected Command getElseCommand(){
		return this.elseCommand;
	}
	/**
	 * Initialize this new If with the given parameters.
	 * @param 	condition
	 * 			The condition of the new If.
	 * @param 	ifCommand
	 * 			The ifCommand of the new If.
	 * @param 	elseCommand
	 * 			The elseCommand of the new If.
	 * @post   	The condition of this new If is the
	 *         	same as the given condition.
	 * @post   	The ifCommand of this new If is the
	 *         	same as the given ifCommand.
	 * @post   	The elseCommand of this new If is the
	 *         	same as the given elseCommand.
	 * @throws 	IllegalConditionException
	 * 			This new If cannot have the given condition.   
	 * @throws 	IllegalCommandException
	 * 			This new If cannot have one of the two given commands.   
	 */
	public If(Condition condition, Command ifCommand, Command elseCommand){
		if(!canHaveAsCondition(condition)){
			throw new IllegalConditionException();
		}
		if(!canHaveAsCommand(ifCommand) || !canHaveAsCommand(elseCommand)){
			throw new IllegalCommandException();
		}
		this.condition = condition;
		this.ifCommand = ifCommand;
		this.elseCommand = elseCommand;
		
	}
	/**
	 * Executes the ifCommand if the condition is true, otherwise it executes the elseCommand.
	 */
	@Override
	public void execute(Robot robot) {
		if(this.getCondition().evaluate(robot)){
			this.getIfCommand().execute(robot);
		}
		else{
			this.getElseCommand().equals(robot);
		}
	}
	
	@Override
	public String toString(){
		return "( if  " + this.getCondition().toString() + this.getIfCommand().toString() +  this.getElseCommand().toString() + " )";
	}
	
	@Override
	public boolean equals(Object object){
		if(object == null || this==null){
			return false;
		}
		return this.toString().equals(object.toString());
	}
	
	@Override
	public void setAlreadyExecuted(boolean alreadyExecuted){
		this.alreadyExecuted = alreadyExecuted;
		this.getIfCommand().setAlreadyExecuted(alreadyExecuted);
		this.getElseCommand().setAlreadyExecuted(alreadyExecuted);
	}
	/**
	 * If the next executeSingleStep should start in the ifCommand.
	 */
	private boolean inIf = false;
	/**
	 * If the next executeSingleStep should start in the elseCommand.
	 */
	private boolean inElse = false;
	
	@Override
	public boolean executeSingleStep(Robot robot) {
		if(!this.isAlreadyExecuted()){
			if(inIf){
				this.getIfCommand().executeSingleStep(robot);
				if(this.getIfCommand().isAlreadyExecuted()){
					this.setAlreadyExecuted(true);
					this.inIf=false;
				}
			}
			else if(inElse){
				this.getElseCommand().executeSingleStep(robot);
				if(this.getElseCommand().isAlreadyExecuted()){
					this.setAlreadyExecuted(true);
					this.inElse=false;
				}
			}
			else{
				if(this.getCondition().evaluate(robot)){
					this.inIf=true;
					this.getIfCommand().executeSingleStep(robot);
					if(this.getIfCommand().isAlreadyExecuted()){
						this.setAlreadyExecuted(true);
						this.inIf=false;
					}
				}
				else{
					this.inElse=true;
					this.getElseCommand().executeSingleStep(robot);
					if(this.getElseCommand().isAlreadyExecuted()){
						this.setAlreadyExecuted(true);
						this.inElse=false;
					}
				}
			}
			return true;
		}
		return false;
	}

	
}
